﻿using SoldiHive.Core.Cache;
using SoldiHive.Core.NodeJs;
using SoldiHive.Core.Parsing;
using SoldiHive.Core.Ratings;
using SoldiHive.Model;

namespace SoldiHive.Core.Adapters
{
	public abstract class BaseAdapter : IRatingsAdapter, SoldiHive.Core.Adapters.ICurrentPriceAdapter
	{
		protected const string GET_CURRENT_PRICE_SCRIPT = "marketwatch_getcurrentprice.js";

		protected IScriptExecutor scriptExecutor;
		protected IParser parser;
		protected IRatingStrategy ratingStrategy;
		protected ICache cache;
		protected IAdapterConfiguration configuration;

		public abstract Site Source 
		{ 
			get;
		}

		public BaseAdapter(IScriptExecutor scriptExecutor, IParser parser, IRatingStrategy ratingStrategy, ICache cache, IAdapterConfiguration configuration)
		{
			this.scriptExecutor = scriptExecutor;
			this.parser = parser;
			this.ratingStrategy = ratingStrategy;
			this.configuration = configuration;
			this.cache = cache;
		}

		public abstract Rating GetRating(Company company);

		protected Rating GetRating(string scriptName, Company company)
		{
			var cacheKey = this.cache.Key(this.Source, "GetRating", company.Ticker);
			if (this.cache.Enabled && this.cache.Has(cacheKey))
			{
				return this.cache.Get<Rating>(cacheKey);
			}

			var result = this.scriptExecutor.Execute(scriptName, company.Ticker);
			if (string.IsNullOrEmpty(result))
			{
				return null;
			}

			var currentPrice = this.GetCurrentPrice(company);
			var opinions = this.parser.ParseAnalystOpinions(result);
			
			var rating = this.ratingStrategy.GetRating(currentPrice, opinions);

			rating.Source = this.Source;

			if (this.cache.Enabled && rating != null)
			{
				this.cache.Put(cacheKey, rating);
			}

			return rating;
		}

		public double GetCurrentPrice(Company company)
		{
			var cacheKey = this.cache.Key(this.Source, "GetCurrentPrice", company.Ticker);
			if (this.cache.Enabled && this.cache.Has(cacheKey))
			{
				return this.cache.Get<double>(cacheKey);
			}

			var result = this.scriptExecutor.Execute(BaseAdapter.GET_CURRENT_PRICE_SCRIPT, company.Ticker);
			if (string.IsNullOrEmpty(result))
			{
				return double.NaN;
			}

			var currentPrice = 0D;
			if (double.TryParse(result, out currentPrice))
			{
				if (this.cache.Enabled)
				{
					this.cache.Put(cacheKey, currentPrice);
				}

				return currentPrice;
			}

			return double.NaN;
		}
	}
}
